﻿using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;

namespace ModuleBase
{
    public abstract class ModuleBase : IModuleBase, INotifyPropertyChanged
    {
        private ModuleStatus _status = ModuleStatus.NotExecuted;
        private string _name;
        public string Name
        {
            get => _name;
            set
            {
                _name = value;
                OnPropertyChanged(nameof(Name));
                OnPropertyChanged(nameof(DisplayName));
            }
        }
        public string Alias { get; set; } = string.Empty;
        public string DisplayName => string.IsNullOrWhiteSpace(Alias) ? Name : Alias;
        public string Id { get; set; }
        public string Category { get; set; }

        private string _templateName;
        public string TemplateName
        {
            get => _templateName;
            set
            {
                _templateName = value;
                OnPropertyChanged(nameof(TemplateName));
            }
        }

        public ModuleStatus Status
        {
            get => _status;
            set
            {
                if (_status != value)
                {
                    _status = value;
                    OnPropertyChanged(nameof(Status));
                }
            }
        }

        protected ModuleBase()
        {
            Id = Guid.NewGuid().ToString();
            // 自动订阅全局状态服务的信号，实现自动响应急停、暂停、恢复等
            try
            {
                var globalState = System.AppDomain.CurrentDomain.GetAssemblies()
                    .SelectMany(a => a.GetTypes())
                    .FirstOrDefault(t => t.FullName == "HostComputerPlatform.Services.GlobalStateService");
                if (globalState != null)
                {
                    var instanceProp = globalState.GetProperty("Instance", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
                    var instance = instanceProp?.GetValue(null);
                    var eventInfo = globalState.GetEvent("ControlSignal");
                    if (eventInfo != null && instance != null)
                    {
                        Action<string> handler = (signal) =>
                        {
                            switch (signal)
                            {
                                case "emergencystopped":
                                    Status = ModuleStatus.EmergencyStopped;
                                    break;
                                case "paused":
                                    Status = ModuleStatus.Paused;
                                    break;
                                case "running":
                                    Status = ModuleStatus.Running;
                                    break;
                                case "idle":
                                    Status = ModuleStatus.Idle;
                                    break;
                            }
                        };
                        var d = Delegate.CreateDelegate(eventInfo.EventHandlerType, handler.Target, handler.Method);
                        eventInfo.AddEventHandler(instance, d);
                    }
                }
            }
            catch { /* 忽略反射异常，防止设计时出错 */ }
        }
        public virtual Dictionary<string, object> GetProperties()
        {
            return new Dictionary<string, object>();
        }
        public virtual Dictionary<string, List<object>> PropertyOptions { get; } = new Dictionary<string, List<object>>();
        public Dictionary<string, string> DisplayNameToPropertyNameMap { get; set; } = new Dictionary<string, string>();
        public virtual void Initialize()
        {
            // 默认实现重置执行状态
            Status = ModuleStatus.NotExecuted;
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public void SetProperties(Dictionary<string, object> properties)
        {
            foreach (var property in properties)
            {
                var propertyName = DisplayNameToPropertyNameMap.ContainsKey(property.Key)
                    ? DisplayNameToPropertyNameMap[property.Key]
                    : property.Key;

                var propertyInfo = GetType().GetProperty(propertyName);
                if (propertyInfo != null && propertyInfo.CanWrite)
                {
                    object value = property.Value;

                    if (value is System.Text.Json.JsonElement jsonElement)
                    {
                        value = ConvertJsonElement(jsonElement, propertyInfo.PropertyType);
                    }

                    propertyInfo.SetValue(this, value);
                }
            }
        }

        private object ConvertJsonElement(System.Text.Json.JsonElement jsonElement, Type targetType)
        {
            if (targetType == typeof(double))
            {
                return jsonElement.GetDouble();
            }
            else if (targetType == typeof(int))
            {
                return jsonElement.GetInt32();
            }
            else if (targetType == typeof(string))
            {
                return jsonElement.GetString();
            }
            else if (targetType == typeof(bool))
            {
                return jsonElement.GetBoolean();
            }
            else
            {
                throw new NotSupportedException($"不支持的类型: {targetType}");
            }
        }
        //public abstract Dictionary<string, object> Execute(Dictionary<string, object> inputs, ExecutionContext context);
        public abstract bool Execute();

        //public abstract Task<Dictionary<string, object>> ExecuteAsync(Dictionary<string, object> inputs, ExecutionContext context);
        public abstract Task<bool> ExecuteAsync();

        public event Action<string> ExecutionResultEvent;

        protected void OnExecutionResult(string message)
        {
            ExecutionResultEvent?.Invoke(message);
        }

        public virtual string Description => string.Empty;
    }
}